package org.jeecg.modules.hc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.hc.constant.RedisConstant;
import org.jeecg.modules.hc.entity.HcCommodity;
import org.jeecg.modules.hc.entity.HcMerchant;
import org.jeecg.modules.hc.entity.HcShoppingCart;
import org.jeecg.modules.hc.entity.HcSiteAddressDetails;
import org.jeecg.modules.hc.enums.HcBusinessStateEnum;
import org.jeecg.modules.hc.enums.HcIsFlagEnum;
import org.jeecg.modules.hc.mapper.HcShoppingCartMapper;
import org.jeecg.modules.hc.service.IHcCommodityService;
import org.jeecg.modules.hc.service.IHcMerchantService;
import org.jeecg.modules.hc.service.IHcShoppingCartService;
import org.jeecg.modules.hc.service.IHcSiteAddressDetailsService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 购物车
 * @Author: jeecg-boot
 * @Date: 2022-12-13
 * @Version: V1.0
 */
@Service
public class HcShoppingCartServiceImpl extends ServiceImpl<HcShoppingCartMapper, HcShoppingCart> implements IHcShoppingCartService {

    @Resource
    private HcShoppingCartMapper hcShoppingCartMapper;

    @Autowired
    private IHcCommodityService hcCommodityService;

    @Autowired
    private IHcMerchantService hcMerchantService;

    @Autowired
    private IHcSiteAddressDetailsService hcSiteAddressDetailsService;

    @Autowired
    private RedisUtil redisUtil;

    public void checkCommodityRequired(List<HcMerchant> hcMerchantShoppingList, String addressId) {
        for (HcMerchant hcMerchant : hcMerchantShoppingList) {
            hcMerchantService.setInformation(hcMerchant);

            if (HcBusinessStateEnum.NO.equals(hcMerchant.getBusinessState()) || HcBusinessStateEnum.NO_ADMIN.equals(hcMerchant.getBusinessState())) {
                throw new JeecgBootException(hcMerchant.getStoreName() + "打烊中不能下单");
            } else {
                hcMerchantService.checkBusinessState(hcMerchant);

                if (HcBusinessStateEnum.NO.equals(hcMerchant.getBusinessState()) || HcBusinessStateEnum.NO_ADMIN.equals(hcMerchant.getBusinessState())) {
                    throw new JeecgBootException(hcMerchant.getStoreName() + "打烊中不能下单");
                }
            }

            if (StringUtils.isNotBlank(addressId)) {
                HcSiteAddressDetails hcSiteAddressDetails = hcSiteAddressDetailsService.getById(addressId);

                if (!hcMerchant.getSiteId().contains(hcSiteAddressDetails.getSiteId())) {
                    throw new JeecgBootException(hcMerchant.getStoreName() + "不在配送范围内，请重新选择");
                }
            }

            List<String> requiredIds = hcCommodityService.listObjs(new LambdaQueryWrapper<HcCommodity>()
                            .select(HcCommodity::getId)
                            .eq(HcCommodity::getMerchantId, hcMerchant.getId())
                            .eq(HcCommodity::getRequiredFlag, HcIsFlagEnum.YES)
                    , Object::toString
            );

            if (!CollectionUtils.isEmpty(requiredIds)) {
                List<HcShoppingCart> hcShoppingCartList = hcMerchant.getHcShoppingCartList();

                boolean flag = false;
                int noRequireCount = 0;

                for (HcShoppingCart hcShoppingCart : hcShoppingCartList) {
                    if (requiredIds.contains(hcShoppingCart.getCommodityId())) {
                        flag = true;
                    } else {
                        noRequireCount++;
                    }
                }

                if (noRequireCount == 0) {
                    throw new JeecgBootException(hcMerchant.getStoreName() + "门店需要点一个以上商品才可以配送哦！");
                }

                if (!flag) {
                    throw new JeecgBootException(hcMerchant.getStoreName() + "门店需添加必选商品才可下单");
                }
            }
        }
    }

    public void setShoppingCartCount(HcCommodity hcCommodity, String userId) {
        Object o = redisUtil.hget(RedisConstant.HC_SHOPPING + userId, hcCommodity.getId());

        if (o != null) {
            hcCommodity.setShoppingCartCount(Integer.valueOf(o.toString()));
        } else {
            hcCommodity.setShoppingCartCount(0);
        }
    }

    public void add(HcShoppingCart param) {
        HcShoppingCart shoppingCartSave = new HcShoppingCart();

        String commodityId = param.getCommodityId();
        HcCommodity hcCommodity = hcCommodityService.getById(commodityId);

        if (hcCommodity == null || hcCommodity.getDelFlag() == 1) {
            throw new JeecgBootException("菜品不存在，请刷新页面重试");
        }

        shoppingCartSave.setUserId(param.getUserId());
        shoppingCartSave.setCommodityId(commodityId);
        shoppingCartSave.setMerchantId(hcCommodity.getMerchantId());
        shoppingCartSave.setCommodityQuantity(param.getCommodityQuantity());

        LambdaQueryWrapper<HcShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<HcShoppingCart>()
                .eq(HcShoppingCart::getUserId, shoppingCartSave.getUserId())
                .eq(HcShoppingCart::getCommodityId, shoppingCartSave.getCommodityId())
                .last(" limit 1 ");

        //如果商品开启了规格 则必须要传规格
        if (hcCommodity.getSpecificationsFlag().equals(HcIsFlagEnum.YES)) {
            if (StringUtils.isBlank(param.getCommoditySpecifications())) {
                throw new JeecgBootException("规格不能为空");
            }

            String[] split = param.getCommoditySpecifications().split(",");
            Arrays.sort(split);
            String join = StringUtils.join(split, ',');

            HcCommodity checkSpecifications = hcCommodityService.checkSpecifications(hcCommodity, param.getAddressId(), join);

            System.out.println(checkSpecifications);
            if (checkSpecifications == null) {
                throw new JeecgBootException("规格校验错误");
            }

            shoppingCartSave.setCommoditySpecifications(join);

            if (checkSpecifications.getCommodityPrice() == null || checkSpecifications.getCommodityPrice().compareTo(new BigDecimal(0)) < 0) {
                throw new JeecgBootException("价格错误，请联系管理员");
            }

            shoppingCartSave.setCommodityPrice(checkSpecifications.getCommodityPrice().multiply(new BigDecimal(param.getCommodityQuantity())));

            lambdaQueryWrapper.eq(HcShoppingCart::getCommoditySpecifications, join);
        } else {
            HcCommodity checkSpecifications = hcCommodityService.checkSpecifications(hcCommodity, param.getAddressId(), null);

            if (checkSpecifications.getCommodityPrice() == null || checkSpecifications.getCommodityPrice().compareTo(new BigDecimal(0)) < 0) {
                throw new JeecgBootException("价格错误，请联系管理员");
            }

            shoppingCartSave.setCommodityPrice(checkSpecifications.getCommodityPrice().multiply(new BigDecimal(param.getCommodityQuantity())));
        }

        HcShoppingCart hcShoppingCart = this.getOne(lambdaQueryWrapper);

        if (hcShoppingCart == null) {
            if (shoppingCartSave.getCommodityQuantity() < 1) {
                shoppingCartSave.setCommodityQuantity(1);
            }

            this.save(shoppingCartSave);
            redisUtil.hset(RedisConstant.HC_SHOPPING + shoppingCartSave.getUserId(), shoppingCartSave.getCommodityId(), shoppingCartSave.getCommodityQuantity());
        } else {
            int quantity = hcShoppingCart.getCommodityQuantity() + param.getCommodityQuantity();

            if (quantity <= 0) {
                this.removeById(hcShoppingCart.getId());

                redisUtil.hdel(RedisConstant.HC_SHOPPING + shoppingCartSave.getUserId(), shoppingCartSave.getCommodityId());
            } else {
                this.updateById(new HcShoppingCart().setId(hcShoppingCart.getId())
                        .setCommodityQuantity(quantity)
                );

                redisUtil.hset(RedisConstant.HC_SHOPPING + shoppingCartSave.getUserId(), shoppingCartSave.getCommodityId(), quantity);
            }
        }
    }

    /**
     * @param hcShoppingCart 购物车中的一条记录，一条记录包括 商品，规格（），商品数量，以及 商品数量 * (商品价格 + 规格价格) 计算出，单条录总价格
     * @param hcCommodity 购物车中的记录对应的商品的商品详情
     * @param addressId 用户所在大厦id
     * @return
     */
    public Boolean checkCommodity(HcShoppingCart hcShoppingCart, HcCommodity hcCommodity, String addressId) {
        Boolean result = null;

        if (hcCommodity == null || hcCommodity.getDelFlag() == 1) {
            // 若用户购物车中的商品在 hc_commodity表中没有对应商品，可能是用户添加到购物车后，支付前，商品下架了，此时将此商品从用户购物车中移除
            this.removeById(hcShoppingCart.getId()); // delete from hc_shopping_cart where id = <商品id>
        } else if (hcCommodity.getSpecificationsFlag().equals(HcIsFlagEnum.YES)) {
            //判断购物车数据里是否有规格，没有规格则删除数据
            if (StringUtils.isBlank(hcShoppingCart.getCommoditySpecifications())) {
                // 若通过 hc_shopping_cart 中的 commodity_id 查询 hc_commodity 表，查询的商品有规格，但是购物车中该商品的记录的规格为空，
                // 则表示添加到购物车中时，商品还没有规格，添加后，商品有了规格，对于此类商品，从购物车中移除；
                // 推测此处逻辑是为了修复数据库结构变化后的bug，修复没有 规格 功能之前的数据，导致有规格功能后的数据，无法正常在页面上显示的问题
                this.removeById(hcShoppingCart.getId());
            } else {
                //判断购物车规格的数量和菜品规格的数量是否一致，不一致删除购物车数据
                HcCommodity checkSpecifications = hcCommodityService.checkSpecifications(hcCommodity, addressId, hcShoppingCart.getCommoditySpecifications());

                if (checkSpecifications == null) {
                    // checkSpecifications 类型为 hcCommodity，为null表示购物车中保存的商品规格信息和商品自身的规格信息不一致，从购物车中移除该商品
                    this.removeById(hcShoppingCart.getId());
                } else {
                    BigDecimal multiply = checkSpecifications.getCommodityPrice().multiply(new BigDecimal(hcShoppingCart.getCommodityQuantity()));

                    if (multiply.compareTo(hcShoppingCart.getCommodityPrice()) != 0) {
                        result = false;
                        hcShoppingCart.setCommodityPrice(multiply);
                        this.updateById(new HcShoppingCart().setId(hcShoppingCart.getId()).setCommodityPrice(multiply));
                    } else {
                        result = true;
                    }
                }
            }
        } else if (hcCommodity.getSpecificationsFlag().equals(HcIsFlagEnum.NO)) {
            //如果商品没启用规格但是购物车里有规格 则删除数据
            if (StringUtils.isNotBlank(hcShoppingCart.getCommoditySpecifications())) {
                this.removeById(hcShoppingCart.getId());
            } else {
                HcCommodity checkSpecifications = hcCommodityService.checkSpecifications(hcCommodity, addressId, hcShoppingCart.getCommoditySpecifications());
                BigDecimal multiply = checkSpecifications.getCommodityPrice().multiply(new BigDecimal(hcShoppingCart.getCommodityQuantity()));

                if (multiply.compareTo(hcShoppingCart.getCommodityPrice()) != 0) {
                    result = false;
                    hcShoppingCart.setCommodityPrice(multiply);
                    this.updateById(new HcShoppingCart().setId(hcShoppingCart.getId()).setCommodityPrice(multiply));
                } else {
                    result = true;
                }
            }
        }

        //校验门店是否删除
        if (hcCommodity != null && StringUtils.isNotBlank(hcCommodity.getMerchantId())) {
            HcMerchant hcMerchant = hcMerchantService.getById(hcCommodity.getMerchantId());

            if (hcMerchant == null || hcMerchant.getDelFlag() == 1) {
                this.removeById(hcShoppingCart.getId());
            }
        }

        return result;
    }

    public List<HcMerchant> getListByUser(String userId, String addressId) {
        // 查询用户购物车中的 所有商品
        List<HcShoppingCart> listByUser = hcShoppingCartMapper.getListByUser(userId);
        Map<String, HcMerchant> map = new HashMap<>();

        for (HcShoppingCart hcShoppingCart : listByUser) {
            Boolean checkCommodity = this.checkCommodity(hcShoppingCart, hcShoppingCart.getHcCommodity(), addressId);

            if (checkCommodity == null) {
                continue;
            }

            Integer remainingQuantity = hcCommodityService.getRemainingQuantity(hcShoppingCart.getHcCommodity());
            hcShoppingCart.setRemainingQuantity(remainingQuantity);

            //根据商户分组set数据,一个用户可能从多个商户哪里购买多个商品，将用户购买的商品按照商户进行分类
            HcMerchant hcMerchant = hcShoppingCart.getHcMerchant();

            if (map.containsKey(hcShoppingCart.getMerchantId())) {
                hcMerchant = map.get(hcShoppingCart.getMerchantId());
            }

            List<HcShoppingCart> hcShoppingCartList = hcMerchant.getHcShoppingCartList() == null ? new ArrayList<>() : hcMerchant.getHcShoppingCartList();
            HcShoppingCart target = new HcShoppingCart();
            BeanUtils.copyProperties(hcShoppingCart, target, "hcMerchant");
            hcShoppingCartList.add(target);
            hcMerchant.setHcShoppingCartList(hcShoppingCartList);
            map.put(hcShoppingCart.getMerchantId(), hcMerchant);
        }

        List<HcMerchant> collect = map.values().stream().collect(Collectors.toList());
        return collect;
    }
}
